/**
 * Classe permettant le choix du mode de lancement de l'application, et permettant la génération d'appels d'ascenseurs dans le cas d'une simulation.
 * @authors: Nicolas BOUQUIN,  Bertrand GUILLAUMOND
 * @version 1.0
 */

import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;

public class Simulation{

	private boolean randomMode;	
	private Config configuration;
	public ConsoleFrame console;
	java.util.Timer t;
	private Vector <Customer> clones = new Vector<Customer>();
    
    /*private Vector <Integer> zoneSS = new <Integer> Vector();
	private Vector <Integer> zoneRDC = new <Integer> Vector();
	private Vector <Integer> zoneSI = new <Integer> Vector(); // Vecteurs d'appels par zone 
	private Vector <Integer> zoneM = new <Integer> Vector();
	private Vector <Integer> zoneH = new <Integer> Vector();*/

	public Simulation(){
		randomMode = true;
		ModeChoiceDialog d = new ModeChoiceDialog(new JFrame());
		Options opt = new Options();
		Point p = new Point();
		p.setLocation(d.getLocation().getX() + 500, d.getLocation().getY()-200);
		
		console = new ConsoleFrame();
		console.setLocation(p);
		configuration = new Config(console);
		configuration.read();
		
		d.startDialog(opt);

		chooseMode(opt.getMode());
		start();
	}

	public void chooseMode(int mode)
	{
		if(mode == 1)
			randomMode = true;
		else
			randomMode = false;
	}

	public static void updateConfig()
	{
	
	}

	public void doMoveElevator()
	{

	}	
		
	public void start()
	{
		
		if(randomMode)
		{
			startRandomSimulation();
		}
		else{
			startEventSimulation();
		}
	}

	public void startEventSimulation()
	{
		Random rand = new Random();
		
		
		Building b = new Building(console, configuration);
		b.calculateBackPosition();
		EventSimulationFrame eventFrame = new EventSimulationFrame(b);
		
		Gui Interface = b.getInterface();
		Point p = new Point();
		p.setLocation(Interface.getLocation().getX() + 480, Interface.getLocation().getY());
		eventFrame.setLocation(p);
		p = new Point();
		p.setLocation(Interface.getLocation().getX() + 480, Interface.getLocation().getY()-200);
		console.setLocation(p);
		Elevator[] elevators;
		elevators = b.getElevators();
	
		int r = 0;

		int floor = 0;
		int current;

		

		/*boolean goon = true;
		while(goon)
		{
			refresh(b, Interface);
			try{
			  Thread.currentThread().sleep(configuration.getRefreshDelay());
			}
			catch(InterruptedException ie){
			
			}
		}*/
		globalRefresh(b, Interface);	
	}

	public void startRandomSimulation()
	{
		Random rand = new Random();
		Building b = new Building(console,configuration);
		b.calculateBackPosition();
		Gui Interface = b.getInterface();
		
		Customer[] customers = new Customer[3];
		Elevator[] elevators;
		
		elevators = b.getElevators();

		int r = 0;

		int floor = 0;
		int current;
		
		/*for(int i = 0; i < 3; i++){
			customers[i] = new Customer(rand.nextInt(44), rand.nextInt(44));
			b.callElevator(customers[i], customers[i].getCurrentFloor(), customers[i].getDestination());
		}*/

		/*boolean goon = true;
		while(goon)
		{
			refresh(b, Interface);
			try{
			  Thread.currentThread().sleep(500);
			}
			catch(InterruptedException ie){
			
			}
		}*/
		globalRefresh(b, Interface);	
			
	}
	
	public void globalRefresh(Building b, Gui g) {
   	 t = new java.util.Timer();
   	 t.schedule(new Refresh(b,g,t,1*configuration.getRefreshDelay()), 0, 1*configuration.getRefreshDelay());
    }
	

	public void refresh(Building b, Gui Interface)
	{
		b.refresh();
		Interface.refresh();
	}

	private class Refresh extends TimerTask {
		
		private Building schBuilding;
		private Gui schInterface;
		private java.util.Timer schTimer;
		int schRefresh;
		public Refresh(Building b, Gui g, java.util.Timer t, int refreshDelay)
		{
			schBuilding = b;
			schInterface = g;
			schTimer = t;
			schRefresh = refreshDelay;
		}
		
		public void run() {
			if(randomMode)
				generateRandomCall(schBuilding);
			if(1*configuration.getRefreshDelay() != schRefresh)
			{
				schTimer.cancel();
				schTimer = new java.util.Timer();
				schTimer.schedule(new Refresh(schBuilding,schInterface,schTimer,1*configuration.getRefreshDelay()), 0, 1*configuration.getRefreshDelay());
			}
			refresh(schBuilding, schInterface);
		}
    }

	public void generateRandomCall(Building b)
	{
		//ponderation
		Random ponderation = new Random();
		int zone,etage = 0;
        int modulo = 1;
        Float nbProba;
        if (configuration.isDay())
        {
            if (configuration.isWeek())
                nbProba = 50*(100/ new Float(configuration.getRefreshDelay()));
            else                
                 nbProba = 150*(100/new Float(configuration.getRefreshDelay()));     
        }        
        else
        {
             nbProba = 300*(100/new Float(configuration.getRefreshDelay()));
        }        

        modulo = Math.round(nbProba);
   	
		if(ponderation.nextInt() % modulo  == 0 || clones.size() == 0)
		{		
			zone = ponderation.nextInt(20);	
			if (configuration.isDay() && configuration.isWeek())
			{			
				if (zone == 0)
				{
					etage = ponderation.nextInt(4);
					//zoneSS.add(new Integer(etage)); 
				}				
				else if (zone >= 1 && zone < 9)
				{
					etage = 4;
					//zoneRDC.add(new Integer(etage));                    
				}				
				else if (zone >= 9 && zone < 13)
				{				
					etage = ponderation.nextInt(20)+5;
					//zoneSI.add(new Integer(etage)); 
				}
				else if (zone >= 13 && zone < 16)
				{
					etage = ponderation.nextInt(15)+25;
					//zoneM.add(new Integer(etage)); 
				}
				else if (zone >= 16 && zone < 20)
				{
					etage = ponderation.nextInt(5)+40;
					//zoneH.add(new Integer(etage)); 
				}
				Customer c =  new Customer(etage, ponderation.nextInt(44));
				clones.add(c);
				b.callElevator(c, c.getCurrentFloor(), c.getDestination());				
			}
			else
			{
				if (zone >= 0 && zone < 5)
				{
					etage = ponderation.nextInt(4);
					//zoneSS.add(new Integer(etage)); 
				}
				else if (zone >= 5 && zone < 10)
				{
					etage = 4;
					//zoneRDC.add(new Integer(etage)); 
				}
				else if (zone == 10)
				{
					etage = ponderation.nextInt(15)+25;
					//zoneM.add(new Integer(etage)); 
				}
				else if (zone >= 11 && zone < 20)
				{
					etage = ponderation.nextInt(5)+40;
					//zoneH.add(new Integer(etage)); 
				}
				Customer c =  new Customer(etage, ponderation.nextInt(44));
				clones.add(c);
				b.callElevator(c, c.getCurrentFloor(), c.getDestination());								
			}
			
            //Affichage des pourcentages d'appels
            /*float num = new Float(zoneSS.size());
            float den = new Float(clones.size());
            float val = (num/den)*100;
		    System.out.println("Pourcentage Sous-Sol : " + val);

            num = new Float(zoneRDC.size());            
            val = (num/den)*100;
		    System.out.println("Pourcentage RDC : " + val);

            num = new Float(zoneSI.size());
            val = (num/den)*100;
		    System.out.println("Pourcentage Sociétés indépendantes : " + val);

            num = new Float(zoneM.size());            
            val = (num/den)*100;
		    System.out.println("Pourcentage Multinationale : " + val);
            
            num = new Float(zoneH.size());            
            val = (num/den)*100;
		    System.out.println("Pourcentage Hotel : " + val);*/
		}		
	}

	private class ModeChoiceDialog extends JDialog implements ActionListener
	{
        private JPanel topPanel;
		private JPanel midPanel;
		private JPanel lowPanel;
		private JButton randomButton;
		private JButton eventButton;
		private JLabel mainTitle = new JLabel("<html><h1>Simulation</h1></html>");
		private Options op = null;
	
		public ModeChoiceDialog(JFrame parent)
		{
			super(parent,"Choix du mode de fonctionnement",true);
			setLayout(new GridLayout(3,0,10,10));
			topPanel = new JPanel();
			midPanel = new JPanel();
			lowPanel = new JPanel();

			topPanel.setLayout(new FlowLayout());
			midPanel.setLayout(new FlowLayout());
			lowPanel.setLayout(new FlowLayout());
			
			getContentPane().add(topPanel);
			getContentPane().add(midPanel);
			getContentPane().add(lowPanel);

			addButtons();
			addEvents();

			setSize(500,200);
		}

		public void addButtons()
		{
			topPanel.add(mainTitle);
			
			randomButton = new JButton("Mode aléatoire");
			midPanel.add(randomButton);
			
			eventButton = new JButton("Mode saisie d'évènements");
			lowPanel.add(eventButton);
		}

		public void addEvents()
		{
			randomButton.addActionListener(this);
			eventButton.addActionListener(this);
		}

		public void actionPerformed(ActionEvent ev)
		{	
            if(op == null){
				System.out.println("Erreur actionPerformed : les options ne sont pas initialisées");
				return;
			}
			if(ev.getSource() == randomButton)
            {
                op.setMode(1);			
                RandomSettingsDialog rd = new RandomSettingsDialog(this);
                rd.setVisible(true);
            }			
            if(ev.getSource() == eventButton)
				op.setMode(0);

			setVisible(false);
		}
	
		
		public void startDialog(Options opt)
		{
			if(opt == null)
				System.out.println("Erreur dans startDialog : les options ne sont pas initialisées");
			op = opt;
			setVisible(true);
		}       
	
    }

    private class RandomSettingsDialog extends JDialog implements ActionListener
    {	
        private JPanel topPanel;
		private JPanel midPanel;
		private JPanel lowPanel;
        private JLabel title = new JLabel("<html><h1>Réglages</h1></html>");
        private JLabel tranche = new JLabel("Tranche : ");
        private JLabel periode = new JLabel("Période : ");        
        private JLabel economie = new JLabel("Mode d'économie : ");
        private JLabel modeRepositionnement = new JLabel("Mode de repositionnement : ");

        private String[] periodLabels = {"Semaine", "Weekend" };
	    private String[] timeLabels = {"Jour", "Nuit" };
	    private String[] modeLabels = {"Economie d'énergie", "Economie de déplacement", "Pondération de l'un par l'autre"};
	    private String[] positionLabels = {"Repositionnement standard", "Repostionnement par zone","Repositionnement optimisé"};
                
        private JComboBox time = new JComboBox(timeLabels);
		private JComboBox period = new JComboBox(periodLabels);
		private JComboBox mode = new JComboBox(modeLabels);
		private JComboBox position = new JComboBox(positionLabels);
		private JButton launchButton = new JButton("Lancer la simulation");

        public RandomSettingsDialog(JDialog parent)
	    {
		    super(parent,"Réglages du mode Aléatoire",true);
            setLayout(new GridLayout(3,1));
			topPanel = new JPanel();
			midPanel = new JPanel();
			lowPanel = new JPanel();

			topPanel.setLayout(new FlowLayout());
			midPanel.setLayout(new GridLayout(4,2));
			lowPanel.setLayout(new FlowLayout());
			
			getContentPane().add(topPanel);
			getContentPane().add(midPanel);
			getContentPane().add(lowPanel);           

			addButtons();
			addEvents();
		    setSize(500,200);
	    }

        public void addButtons()
		{
            topPanel.add(title);
			
			midPanel.add(tranche);
            midPanel.add(time);
            midPanel.add(periode);
            midPanel.add(period);
            midPanel.add(economie);
            midPanel.add(mode);
            midPanel.add(modeRepositionnement);
            midPanel.add(position);
			
			lowPanel.add(launchButton);
		}

		public void addEvents()
	    {
            time.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
				    boolean value = time.getSelectedIndex() == 0 ? true : false;
                    configuration.setDay(value);
                }
            });

            period.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
				    boolean value = period.getSelectedIndex() == 0 ? true : false;
                    configuration.setWeek(value);
                }
            });

            mode.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    configuration.setEnergyMode(mode.getSelectedIndex());
                }
            });

		    position.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    configuration.setReturnMode(position.getSelectedIndex());
                }
            });
            launchButton.addActionListener(this);

	    }

        public void actionPerformed(ActionEvent ev)
		{	
            if(ev.getSource() == launchButton)
            {
               setVisible(false);
               dispose();
            }			
		}
    }

    


   private class Options
   {
	  	public int mode;
	  	
	  	public Options(){
			mode = 0;
		}
	  	
	  	public void setMode(int m)
	  	{
		  mode = m;
	  	}

		public int getMode()
		{
			return mode;
		}
   }
}
